#include "bo3d.h"

// Creates a new named SceneNode as a child of this node.
BBDECL Ogre::SceneNode* __stdcall o_createChildSceneNode(Ogre::SceneNode* node, const char* entityName, boVec3* translate, boQuaternion* rotate)
{
	Ogre::Vector3 vec3 = Ogre::Vector3::ZERO;
	Ogre::Quaternion q = Ogre::Quaternion::IDENTITY;
	Ogre::SceneNode* child; 

	if(translate != NULL) vec3 = Ogre::Vector3(Ogre::Real(translate->x), Ogre::Real(translate->y), Ogre::Real(translate->z));
	if(rotate != NULL) q = Ogre::Quaternion(Ogre::Real(rotate->w), Ogre::Real(rotate->x), Ogre::Real(rotate->y), Ogre::Real(rotate->z));

	try
	{
		child = node->createChildSceneNode(Ogre::String(entityName), vec3, q);
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}

	return child;
}


// (BlitzPlus/Blitz3D) Creates a new named SceneNode as a child of this node.
BBDECL Ogre::SceneNode* __stdcall bb_createChildSceneNode(Ogre::SceneNode* node, const char* entityName)
{
	Ogre::SceneNode* child;

	try
	{
		child = node->createChildSceneNode(Ogre::String(entityName));
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}

	return child;
}

// Adds an instance of a scene object to this node. 
BBDECL void __stdcall o_attachObject(Ogre::SceneNode* node, Ogre::MovableObject* obj)
{
	try
	{
		node->attachObject(obj);
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}
}

BBDECL const char* __stdcall o_getName(Ogre::MovableObject* obj)
{
	const char* name;
	try
	{
		name = reinterpret_cast<Ogre::MovableObject*>(obj)->getName().c_str();
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}

	return name;
}

BBDECL const char* __stdcall o_getType(Ogre::MovableObject* obj)
{
	const char* type;

	try
	{
		type = obj->getMovableType().c_str();
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}

	return type;
}

// Rotate the node around the X-axis. 
BBDECL void __stdcall o_scenenode_pitch(Ogre::SceneNode* node, float angle, int relativeTo)
{
	try
	{
		Ogre::Node::TransformSpace ts;
		switch(relativeTo)
		{
		case 1	: ts = Ogre::Node::TS_LOCAL; break;
		case 2	: ts = Ogre::Node::TS_PARENT; break;
		case 3	: ts = Ogre::Node::TS_WORLD; break;
		default	: ts = Ogre::Node::TS_PARENT;
		}

		node->pitch(Ogre::Radian(angle), ts);
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}
}

// Rotate the node around the Y-axis. 
BBDECL void __stdcall o_scenenode_yaw(Ogre::SceneNode* node, float angle, int relativeTo)
{
	try
	{
		Ogre::Node::TransformSpace ts;
		switch(relativeTo)
		{
		case 1	: ts = Ogre::Node::TS_LOCAL; break;
		case 2	: ts = Ogre::Node::TS_PARENT; break;
		case 3	: ts = Ogre::Node::TS_WORLD; break;
		default	: ts = Ogre::Node::TS_PARENT;
		}

		node->yaw(Ogre::Radian(angle), ts);
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}
}

// Rotate the node around the Z-axis. 
BBDECL void __stdcall o_scenenode_roll(Ogre::SceneNode* node, float angle, int relativeTo)
{
	try
	{
		Ogre::Node::TransformSpace ts;
		switch(relativeTo)
		{
		case 1	: ts = Ogre::Node::TS_LOCAL; break;
		case 2	: ts = Ogre::Node::TS_PARENT; break;
		case 3	: ts = Ogre::Node::TS_WORLD; break;
		default	: ts = Ogre::Node::TS_PARENT;
		}

		node->roll(Ogre::Radian(angle), ts);
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}
}

// Moves the node along the Cartesian axes. 
BBDECL void __stdcall o_scenenode_translate(Ogre::SceneNode* node, float x, float y, float z, int relativeTo)
{
	try
	{
		Ogre::Node::TransformSpace ts;
		switch(relativeTo)
		{
		case 1	: ts = Ogre::Node::TS_LOCAL; break;
		case 2	: ts = Ogre::Node::TS_PARENT; break;
		case 3	: ts = Ogre::Node::TS_WORLD; break;
		default	: ts = Ogre::Node::TS_PARENT;
		}

		node->translate(Ogre::Real(x), Ogre::Real(y), Ogre::Real(z), ts);
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}
}

// Sets the position of the node relative to it's parent. 
BBDECL void __stdcall o_scenenode_setposition(Ogre::SceneNode* node, float x, float y, float z)
{
	try
	{
		node->setPosition(Ogre::Real(x), Ogre::Real(y), Ogre::Real(z));
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}
}

BBDECL boVec3* __stdcall o_scenenode_getposition(Ogre::SceneNode* node)
{
	boVec3* pos = new boVec3;

	try
	{
		Ogre::Vector3 vec = node->getPosition();
		pos->x = vec.x;
		pos->y = vec.y;
		pos->z = vec.z;
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}

	return pos;
}

BBDECL void __stdcall o_scenenode_setOrientation(Ogre::SceneNode* node, boQuaternion* quat)
{
	Ogre::Quaternion q = Ogre::Quaternion(Ogre::Real(quat->w), Ogre::Real(quat->x), Ogre::Real(quat->y), Ogre::Real(quat->z));
	node->setOrientation(q);
}